package myJs.tool

import myJs.Implicits._
import myJs.myPkg.{FileInputJQuery, FileInputOptions, LayerOptions}
import myJs.myPkg.jquery.{$, JQuery, JQueryAjaxSettings, JQueryXHR}
import org.scalajs.dom.{Element, Event}
import org.scalajs.dom.raw.{Blob, BlobPropertyBag}
import scalatags.Text.all._

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import scala.scalajs.js.JSON
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.myPkg.bootstrap.Bootstrap.default._
import myJs.myPkg.bootstrap.jquery.PopoverOptions
import shared.SharedTool

import scala.scalajs.js.Dynamic.{global => g}
import scala.reflect.ClassTag

/** Created by yz on 2019/3/6
  */
@JSExportTopLevel("Tool")
object Tool extends ProjectTool with TableFilterTool with FeatureSelectionTool {

  val confirmButtonClass = "btn-danger"
  val cancelButtonClass = "green"

  val pattern = "yyyy-mm-dd"

  lazy val stateMap = SeqMap(
    "success" -> messages("success"),
    "error" -> messages("failed"),
    "running" -> messages("running"),
    "wait" -> messages("preparing")
  )

  def element(info: String) = {
    div(
      id := "content",
      span(id := "info", info, span(id := "progress", "")),
      " ",
      img(
        src := "/assets/images/running2.gif",
        width := 30,
        height := 20,
        cls := "runningImage"
      )
    ).render
  }

  val wizardId = "wizard"
  lazy val tagMap = SeqMap(
    "animals" -> messages("animals"),
    "bacteria" -> messages("bacteria"),
    "plants" -> messages("plants"),
    "transcriptome" -> messages("transcriptome"),
    "metabolism" -> messages("metabolism"),
    "protein" -> messages("protein"),
    "16s" -> "16S",
    "18s" -> "18S",
    "its" -> "ITS",
    "other" -> messages("other")
  )

  lazy val messages = {
    val url =
      g.jsRoutes.controllers.ToolController.getAllMessages().url.toString
    val ajaxSettings =
      JQueryAjaxSettings.url(s"${url}").`type`("get").async(false).success {
        (data: js.Any, status: String, e: JQueryXHR) =>
          val rs = data.toJDS
          val jsonStr = JSON.stringify(rs)
          g.messages = jsonStr
      }
    $.ajax(ajaxSettings)
    new Messages(Tool.getMessages)
  }
  lazy val loadingElement = element(messages("loadingData"))

  lazy val zhInfo = messages("info")
  lazy val layerOptions = LayerOptions
    .title(zhInfo)
    .closeBtn(0)
    .skin("layui-layer-molv")
    .btn(js.Array())

  lazy val zhRunning = messages("running")
  lazy val myElement = div(id := "content")(
    span(id := "info")(zhRunning),
    " ",
    img(
      src := "/assets/images/running2.gif",
      width := 30,
      height := 20,
      cls := "runningImage"
    )
  ).render

  lazy val isEn = messages("language") == "en"

  def validSep = {
    if (isEn) " " else ""
  }

  def getMessages = {
    g.messages.toString.toJDS
  }

  def getCurLanguage = {
    val language = messages("language")
    language match {
      case "en" => "en"
      case "中文" => "zh"
    }
  }

  def getBTLanguage = {
    val language = Tool.getCurLanguage
    language match {
      case "en" => "en-US"
      case "zh" => "zh-CN"
    }
  }

  def extractor(query: String) = {
    val result = js.RegExp("([^,]+)$").exec(query)
    if (result != null && result(1).isDefined) {
      result(1).toString.trim
    } else ""
  }

  @JSExport("expand")
  def expand(y: Element) = {
    val tool = $(y).parent().find(".tools a:last")
    $(tool).click()

  }

  def getInputByName(name: String) = {
    $(s":input[name='${name}']")
  }

  def getParentElem(parentId: String) = {
    if (parentId.isEmpty) "body" else s"#${parentId}"
  }

  def getParentJq(parentId: String) = {
    val parentElem = getParentElem(parentId)
    $(parentElem)
  }

  def getInputByName(name: String, parentId: String) = {
    val parentElem = Tool.getParentElem(parentId)
    $(s"${parentElem}").findInputByName(name)
  }

  def getInputByValue(value: String) = {
    $(s":input[value='${value}']")
  }

  def getPercent(v: Double) = {
    (v * 100).toInt
  }

  def fillByName(
      rs: js.Dictionary[String],
      name: String,
      parentId: String = ""
  ) = {
    val valOp = rs.get(name)
    valOp.foreach { value =>
      val parentElem = Tool.getParentElem(parentId)
      val jq = $(parentElem).findInputByName(name)
      jq.`val`(value)
      if (jq.hasClass("myMinicolors")) {
        jq.minicolors("value", js.Dictionary("color" -> s"${jq.myVal}"))
      }
    }
  }

  def fillByName(rs: js.Dictionary[String], name: String, parentJq: JQuery) = {
    val valOp = rs.get(name)
    valOp.foreach { value =>
      val jq = parentJq.findInputByName(name)
      jq.`val`(value)
      if (jq.hasClass("myMinicolors")) {
        jq.minicolors("value", js.Dictionary("color" -> s"${value}"))
      }
    }
  }

  @JSExport("fileInput")
  def fileInput = {
    val options = FileInputOptions
      .showPreview(false)
      .browseLabel(s"${messages("selectFile")}...")
      .removeLabel(messages("delete"))
      .language(Tool.getCurLanguage)
      .showUpload(false)
    $(".file").fileinput("destroy")
    $(".file").fileinput(options)
  }

  def fillByNames(rs: js.Dictionary[String], names: Seq[String]) = {
    names.foreach { name =>
      fillByName(rs, name)
    }
  }

  def fillByNames(rs: js.Dictionary[String]) = {
    val names = $(".fillByName").mapElems { y =>
      $(y).attr("name").toString
    }.toArray
    names.foreach { name =>
      fillByName(rs, name)
    }
  }

  def onTabClick: js.Function = (e: Event, a: js.Any, index: Int) => {
    false
  }

  def checkedByNames(rs: js.Dictionary[String], names: Seq[String]) = {
    names.foreach { name =>
      checkedByName(rs, name)
    }
  }

  def checkedByName(rs: js.Dictionary[String], name: String) = {
    rs.get(name) match {
      case Some(value) => $(s":input[name='${name}']").attr("checked", true)
      case None        => $(s":input[name='${name}']").attr("checked", false)
    }
  }

  def fillByNames(rs: js.Dictionary[String], formId: String) = {
    val names = $(s"#${formId} .fillByName").mapElems { y =>
      $(y).attr("name").toString
    }.toArray
    names.foreach { name =>
      fillByName(rs, name, formId)
    }
  }

  def fillByNames(rs: js.Dictionary[String], parentJq: JQuery) = {
    val names = parentJq
      .find(s".fillByName")
      .mapElems { y =>
        $(y).attr("name").toString
      }
      .toArray
    names.foreach { name =>
      fillByName(rs, name, parentJq)
    }
  }

  def fillByIds(rs: js.Dictionary[String]) = {
    val ids = $(s".fillById").mapElems { y =>
      $(y).attr("id").toString
    }.toArray
    ids.foreach { name =>
      fillById(rs, name)
    }
  }

  def fillById(rs: js.Dictionary[String], id: String) = {
    val value = rs(id)
    $(s"#${id}").text(value)
  }

  def fillByNameAndTriggers(rs: JDJAn, names: List[String]): Unit = {
    names.foreach { name =>
      fillByNameAndTrigger(rs, name)
    }
  }

  def fillByNameAndTriggers(rs: JDJAn, parentId: String = ""): Unit = {
    val parentElem = Tool.getParentElem(parentId)
    val parentJq = $(s"${parentElem}")
    fillByNameAndTriggers(rs, parentJq)
  }

  def fillByNameAndTriggers(rs: JDJAn, parentJq: JQuery): Unit = {
    val names = parentJq
      .find(s".fillByNameAndTrigger")
      .mapElems { y =>
        $(y).attr("name").toString
      }
      .toArray
    names.foreach { name =>
      fillByNameAndTrigger(rs, name, parentJq)
    }
  }

  def fillByNameAndTrigger(
      rs: JDJAn,
      name: String,
      parentId: String = ""
  ): JQuery = {
    val parentElem = Tool.getParentElem(parentId)
    val parentJq = $(parentElem)
    fillByNameAndTrigger(rs, name, parentJq)
  }

  def fillByNameAndTrigger(
      rs: JDJAn,
      name: String,
      parentJq: JQuery
  ): JQuery = {
    val jq = parentJq.findInputByName(name)
    val value = rs(name)
    if (jq.hasClass("myToggle")) {
      if (value == null || value == "None" || value.toString == "false") {
        jq.bootstrapToggle("off")
      } else {
        jq.bootstrapToggle("on")
      }
    } else {
      jq.`val`(value.toString).trigger("change")
    }

  }

  def refreshTable(data: js.Any, jq: JQuery, f: () => js.Any = () => ()) = {
    jq.bootstrapTable("load", data)
    f()
  }

  def bindEvt(parentId: String = "") = {
    val parentElem = Tool.getParentElem(parentId)
    val tableId = "table"
    val tableJq = $(s"${parentElem} #${tableId}")
    tableJq
      .on("check.bs.table", () => getIds(parentId))
      .on("uncheck.bs.table", () => getIds(parentId))
      .on("check-all.bs.table", () => getIds(parentId))
      .on("uncheck-all.bs.table", () => getIds(parentId))
      .on("page-change.bs.table", () => getIds(parentId))
  }

  def getIds(parentId: String = "") = {
    val ids = getIdsValue(parentId)
    val parentElem = Tool.getParentElem(parentId)
    if (ids.isEmpty) {
      $(s"${parentElem} .idsButton").attr("disabled", true)
    } else {
      $(s"${parentElem} .idsButton").attr("disabled", false)
    }
  }

  def getIdsValue(parentId: String = "") = {
    val parentElem = Tool.getParentElem(parentId)
    val arrays =
      $(s"${parentElem} #table").bootstrapTable("getSelections").toJArJDJAn
    arrays.map { x =>
      x("id").toString
    }.toList
  }

  def popover = {
    val options = PopoverOptions(container = "body", trigger = "hover")
    $(".selfQuestion").popover(options)
  }

  def b2Display(b: Boolean) = {
    if (b) "block" else "none"
  }

  def getArgI(kinds: List[String], curI: Int) = {
    SharedTool.getIndexMap(kinds)(curI)
  }

}
